package com.guojiang.guoaicodemother.core.saver;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.guojiang.guoaicodemother.ai.model.MultiFileCodeResult;
import com.guojiang.guoaicodemother.exception.BusinessException;
import com.guojiang.guoaicodemother.exception.ErrorCode;
import com.guojiang.guoaicodemother.model.enums.CodeGenTypeEnum;

import java.io.File;
import java.nio.charset.StandardCharsets;

/**
 * 代码文件保存器-抽象统一父类（模板方法模式）
 *
 * @author guojiang
 */
public abstract class CodeFileSaverTemplate<T> {

    /**
     * 文件保存的根目录
     */
    private static final String FILE_SAVE_ROOT_DIR = System.getProperty("user.dir") + "/tmp/code_output";

    /**
     * 模板方法：保存代码文件标准流程，部分步骤推迟到子类实现
     *
     * @param codeParserResult
     * @param appId
     * @return
     */
    public final File saveCodeFile(T codeParserResult, Long appId) {
        // 1. 验证输入是否合法
        validateInput(codeParserResult);
        // 2. 构建唯一目录
        String baseFileDir = buildUniqueDir(appId);
        // 3. 保存文件（具体实现交给子类）
        saveFile(codeParserResult, baseFileDir);
        // 4. 返回文件目录
        return new File(baseFileDir);
    }

    /**
     * 验证输入参数（可以由子类覆盖）
     *
     * @param codeParserResult
     */
    protected void validateInput(T codeParserResult) {
        if (codeParserResult == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "代码解析结果错误");
        }
    }

    /**
     * 写入单个文件的工具方法
     *
     * @param dirPath  目录路径
     * @param fileName 文件名
     * @param content  文件内容
     */
    protected final void writeToFile(String dirPath, String fileName, String content) {
        if (StrUtil.isNotBlank(content)) {
            String filePath = dirPath + File.separator + fileName;
            FileUtil.writeString(content, filePath, StandardCharsets.UTF_8);
        }
    }

    /**
     * 保存多文件的工具方法
     */
    protected final File saveMultiFileCode(MultiFileCodeResult result, String baseDirPath) {
        writeToFile(baseDirPath, "index.html", result.getHtmlCode());
        writeToFile(baseDirPath, "style.css", result.getCssCode());
        writeToFile(baseDirPath, "script.js", result.getJsCode());
        return new File(baseDirPath);
    }

    /**
     * 构建唯一目录路径：tmp/code_output/bizType_appId
     *
     * @param appId
     * @return
     */
    protected String buildUniqueDir(long appId) {
        if (ObjectUtil.isNull(appId) || appId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "应用 ID 不能为空");
        }
        String codeType = getCodeType().getValue();
        // String currentTime = DateUtil.format(new Date(), "yyyy-MM-dd_HH-mm-ss");
        // 为了保证目录唯一性，这里就不用时间了
        String uniqueDirName = StrUtil.format("{}_{}", codeType, appId);
        String dirPath = FILE_SAVE_ROOT_DIR + File.separator + uniqueDirName;
        FileUtil.mkdir(dirPath);
        return dirPath;
    }

    /**
     * 保存文件（具体实现交给子类）
     *
     * @param codeParserResult
     * @param baseFileDir
     */
    protected abstract void saveFile(T codeParserResult, String baseFileDir);

    /**
     * 获取代码类型（具体实现交给子类）
     *
     * @return 代码生成类型枚举
     */
    protected abstract CodeGenTypeEnum getCodeType();
}
